﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
using FlexiCommerce.Persistence;
using FlexiCommerce.Security;
using FlexiCommerce.Web;
using NUnit.Framework;
using Rhino.Mocks;
using Rhino.Mocks.Interfaces;
using FlexiCommerce.Configuration;

namespace FlexiCommerce.Tests.Security
{
    [TestFixture]
    public class SecurityManagerTests : PersistenceAwareBase
    {
        #region Fields
        ISecurityManager security;
        IWebContext context;

        private IEventRaiser moving;
        private IEventRaiser copying;
        private IEventRaiser deleting;
        private IEventRaiser saving;
        #endregion

        #region SetUp
        [SetUp]
        public override void SetUp()
        {
            base.SetUp();
            context = CreateWebContext(false);
            security = new FlexiCommerce.Security.SecurityManager(CreateWebContext(false),engine.Resolve<SecuritySection>());
        }

        #endregion

        [Test]
        public void IsSystemAdmin()
        {
            IPrincipal admin = CreatePrincipal("Cadmin");
            IPrincipal joe = CreatePrincipal("joe");
            mocks.ReplayAll();

            Assert.IsTrue(security.IsSystemAdmin(admin));
            Assert.IsFalse(security.IsSystemAdmin(joe));

            joe = CreatePrincipal("joe", "CAdministrators");

            Assert.IsTrue(security.IsSystemAdmin(joe));
        }

        [Test]
        public void SystemAdminInheritsAllRoles()
        {
            IPrincipal admin = CreatePrincipal("Cadmin");
            Assert.IsTrue(security.IsSystemAdmin(admin));
            Assert.IsTrue(security.IsMarketingManager(admin));
            Assert.IsTrue(security.IsCatalogManager(admin));
            Assert.IsTrue(security.IsOrderManager(admin));
        }

        [Test]
        public void IsMarketingManager()
        {
            IPrincipal marketer = CreatePrincipal("CMarketer");

            Assert.IsTrue(security.IsMarketingManager(marketer));

            marketer = CreatePrincipal("user", "CMarketingManagers");

            Assert.IsTrue(security.IsMarketingManager(marketer));
        }
        [Test]
        public void IsOrderManager()
        {

            IPrincipal ordermanager = CreatePrincipal("COrderManager");

            Assert.IsTrue(security.IsOrderManager(ordermanager));

            ordermanager = CreatePrincipal("user", "COrderManagers");

            Assert.IsTrue(security.IsOrderManager(ordermanager));

        }
        [Test]
        public void IsCatalogManager()
        {

            IPrincipal catalogmanager = CreatePrincipal("CCatalogManager");

            Assert.IsTrue(security.IsCatalogManager(catalogmanager));

            catalogmanager = CreatePrincipal("user", "CCatalogManagers");

            Assert.IsTrue(security.IsCatalogManager(catalogmanager));

        }

        [Test]
        public void GenericUserHasNoSystemRoles()
        {
            IPrincipal user = CreatePrincipal("user");

            Assert.IsFalse(security.IsSystemAdmin(user));
            Assert.IsFalse(security.IsMarketingManager(user));
            Assert.IsFalse(security.IsOrderManager(user));
            Assert.IsFalse(security.IsCatalogManager(user));


            Assert.IsFalse(security.IsSystemAdmin(null));
            Assert.IsFalse(security.IsMarketingManager(null));
            Assert.IsFalse(security.IsOrderManager(null));
            Assert.IsFalse(security.IsCatalogManager(null));

        }
 
        [Test]
        public void IsAuthorized()
        {
            IPrincipal user = CreatePrincipal("user", "role");

            Assert.IsFalse(security.IsAuthorized(user, new string[] {"role2", "role3"}));

            Assert.IsTrue(security.IsAuthorized(user, new string[] { "role", "role2" }));

        }

        //[Test]
        //public void AdministratorsAreAdmins()
        //{
        //    mocks.ReplayAll();

        //    IPrincipal admin = CreatePrincipal("JustAUser", "Administrators");
        //    Assert.IsTrue(security.IsAdmin(admin));
        //}

        //[Test]
        //public void AdminIsEditor()
        //{
        //    mocks.ReplayAll();

        //    IPrincipal admin = CreatePrincipal("admin");
        //    Assert.IsTrue(security.IsEditor(admin));
        //}

        //[Test]
        //public void AdministratorsAreEditors()
        //{
        //    mocks.ReplayAll();

        //    IPrincipal admin = CreatePrincipal("JustAUser", "Administrators");
        //    Assert.IsTrue(security.IsEditor(admin));
        //}

        //[Test]
        //public void EditorsAreEditors()
        //{
        //    mocks.ReplayAll();

        //    IPrincipal editor = CreatePrincipal("JustAnyUser", "Editors");
        //    Assert.IsTrue(security.IsEditor(editor));
        //}

        //[Test]
        //public void EditorsAreNotAdmins()
        //{
        //    mocks.ReplayAll();

        //    IPrincipal editor = CreatePrincipal("JustAnyUser", "Editors");
        //    Assert.IsFalse(security.IsAdmin(editor));
        //}

        //[Test]
        //public void UsersAreNotEditors()
        //{
        //    mocks.ReplayAll();

        //    IPrincipal user = CreatePrincipal("User1");
        //    Assert.IsFalse(security.IsEditor(user));
        //}

        //[Test]
        //public void UsersAreNotAdmins()
        //{
        //    mocks.ReplayAll();

        //    IPrincipal user = CreatePrincipal("User1");
        //    Assert.IsFalse(security.IsAdmin(user));
        //}


        //[Test]
        //public void AuthorizedRolePropertyOnItems()
        //{
        //    mocks.ReplayAll();

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    root.AuthorizedRoles.Add(new N2.Security.AuthorizedRole(root, "Role1"));

        //    IPrincipal user = CreatePrincipal("User1", "Role1");
        //    Assert.IsTrue(security.IsAuthorized(root, user));
        //}

        //[Test]
        //public void AuthorizedRoleDoesNotIncludeUserName()
        //{
        //    mocks.ReplayAll();

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    root.AuthorizedRoles.Add(new N2.Security.AuthorizedRole(root, "User1"));

        //    IPrincipal user = CreatePrincipal("User1");
        //    Assert.IsFalse(security.IsAuthorized(root, user), "User1 shouldn't have has access.");
        //}

        //[Test]
        //public void Unpublished()
        //{
        //    mocks.ReplayAll();

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    root.Published = DateTime.Now.AddDays(1);

        //    IPrincipal user = CreatePrincipal("User1");
        //    Assert.IsFalse(security.IsEditor(user), "Dang! He's editor.");
        //    Assert.IsFalse(security.IsAuthorized(root, user));
        //}

        //[Test]
        //public void NonEditorCannotAccessExpired()
        //{
        //    mocks.ReplayAll();

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    root.Expires = DateTime.Now;

        //    IPrincipal user = CreatePrincipal("User1");
        //    Assert.IsFalse(security.IsAuthorized(root, user));
        //}

        //[Test]
        //public void NonEditorCannotAccessUnpublished()
        //{
        //    mocks.ReplayAll();

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    root.Published = null;

        //    IPrincipal user = CreatePrincipal("User1");
        //    Assert.IsFalse(security.IsAuthorized(root, user));
        //}

        //[Test]
        //public void NonEditorCannotAccessUnpublished2()
        //{
        //    mocks.ReplayAll();

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    root.Published = DateTime.Now.AddSeconds(10);

        //    IPrincipal user = CreatePrincipal("User1");
        //    Assert.IsFalse(security.IsAuthorized(root, user));
        //}

        //[Test]
        //public void ExpiredIsNotPublished()
        //{
        //    mocks.ReplayAll();

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    root.Expires = DateTime.Now;

        //    bool isPublished = security.IsPublished(root);
        //    Assert.IsFalse(isPublished, "Item should not have been published.");
        //}

        //[Test]
        //public void UnpublishedIsNotPublished()
        //{
        //    mocks.ReplayAll();

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    root.Published = null;

        //    bool isPublished = security.IsPublished(root);
        //    Assert.IsFalse(isPublished, "Item should not have been published.");
        //}

        //[Test]
        //public void NotYetPublishedIsNotPublished()
        //{
        //    mocks.ReplayAll();

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    root.Published = DateTime.Now.AddDays(1);

        //    bool isPublished = security.IsPublished(root);
        //    Assert.IsFalse(isPublished);
        //}

        //[Test]
        //public void UserCanSaveAccessibleItem()
        //{
        //    GenericPersistenceItem root = CreateUserAndItem();
        //    mocks.ReplayAll();

        //    saving.Raise(persister, new CancellableItemEventArgs(root));
        //}

        //[Test]
        //public void UserCannotSaveInaccessibleItem()
        //{
        //    GenericPersistenceItem root = SetupNormalUserAndCreateRestrictedItem();
        //    mocks.ReplayAll();

        //    ExceptionAssert.Throws<PermissionDeniedException>(delegate
        //    {
        //        saving.Raise(persister, new CancellableItemEventArgs(root));
        //    });
        //}

        //[Test]
        //public void UserCanDeleteAccessibleItem()
        //{
        //    GenericPersistenceItem root = CreateUserAndItem();
        //    mocks.ReplayAll();

        //    deleting.Raise(persister, new CancellableItemEventArgs(root));
        //}

        //[Test]
        //public void UserCannotDeleteInaccessibleItem()
        //{
        //    GenericPersistenceItem root = SetupNormalUserAndCreateRestrictedItem();
        //    mocks.ReplayAll();

        //    ExceptionAssert.Throws<PermissionDeniedException>(delegate
        //    {
        //        deleting.Raise(persister, new CancellableItemEventArgs(root));
        //    });
        //}

        //[Test]
        //public void UserCanMoveAccessibleItem()
        //{
        //    GenericPersistenceItem source = CreateUserAndItem();
        //    GenericPersistenceItem destination = CreateOneItem<Items.SecurityPage>(2, "accessible page", null);
        //    mocks.ReplayAll();

        //    moving.Raise(persister, new CancellableDestinationEventArgs(source, destination));
        //}

        //[Test]
        //public void UserCannotMoveInaccessibleItem()
        //{
        //    GenericPersistenceItem source = SetupNormalUserAndCreateRestrictedItem();
        //    GenericPersistenceItem destination = CreateOneItem<Items.SecurityPage>(2, "accessible page", null);
        //    mocks.ReplayAll();

        //    ExceptionAssert.Throws<PermissionDeniedException>(delegate
        //    {
        //        moving.Raise(persister, new CancellableDestinationEventArgs(source, destination));
        //    });
        //}

        //[Test]
        //public void UserCannotMoveToInaccessibleItem()
        //{
        //    GenericPersistenceItem destination = SetupNormalUserAndCreateRestrictedItem();
        //    GenericPersistenceItem source = CreateOneItem<Items.SecurityPage>(2, "accessible page", null);

        //    mocks.ReplayAll();
        //    ExceptionAssert.Throws<PermissionDeniedException>(delegate
        //    {
        //        moving.Raise(persister, new CancellableDestinationEventArgs(source, destination));
        //    });
        //}

        //[Test]
        //public void UserCanCopyAccessibleItem()
        //{
        //    GenericPersistenceItem source = CreateUserAndItem();
        //    GenericPersistenceItem destination = CreateOneItem<Items.SecurityPage>(2, "accessible page", null);
        //    mocks.ReplayAll();

        //    copying.Raise(persister, new CancellableDestinationEventArgs(source, destination));
        //}

        //[Test]
        //public void UserCannotCopyInaccessibleItem()
        //{
        //    GenericPersistenceItem source = SetupNormalUserAndCreateRestrictedItem();
        //    GenericPersistenceItem destination = CreateOneItem<Items.SecurityPage>(2, "accessible page", null);
        //    mocks.ReplayAll();

        //    ExceptionAssert.Throws<PermissionDeniedException>(delegate
        //    {
        //        copying.Raise(persister, new CancellableDestinationEventArgs(source, destination));
        //    });
        //}

        //[Test]
        //public void UserCannotCopyToInaccessibleItem()
        //{
        //    GenericPersistenceItem destination = SetupNormalUserAndCreateRestrictedItem();
        //    GenericPersistenceItem source = CreateOneItem<Items.SecurityPage>(2, "accessible page", null);
        //    mocks.ReplayAll();

        //    ExceptionAssert.Throws<PermissionDeniedException>(delegate
        //    {
        //        copying.Raise(persister, new CancellableDestinationEventArgs(source, destination));
        //    });
        //}

        //[Test]
        //public void CanChangeAdminUser()
        //{
        //    IPrincipal user = CreatePrincipal("AverageJoe");
        //    mocks.ReplayAll();

        //    security.AdminNames = new string[] { "AverageJoe" };

        //    Assert.IsTrue(security.IsAdmin(user), "User wasn't admin.");
        //}

        //[Test]
        //public void CanHaveMoreThanOneAdmin()
        //{
        //    IPrincipal maria = CreatePrincipal("SpecialMaria");
        //    IPrincipal bill = CreatePrincipal("SmallBill");
        //    mocks.ReplayAll();

        //    security.AdminNames = new string[] { "AverageJoe", "SpecialMaria", "SmallBill" };

        //    Assert.IsTrue(security.IsAdmin(maria), "User wasn't admin.");
        //    Assert.IsTrue(security.IsAdmin(bill), "User wasn't admin.");
        //}

        //[Test]
        //public void CanChangeAdminRoles()
        //{
        //    IPrincipal user = CreatePrincipal("AverageJoe", "AverageUser", "FriendlyUser");
        //    mocks.ReplayAll();

        //    security.AdminRoles = new string[] { "FriendlyUser" };

        //    Assert.IsTrue(security.IsAdmin(user), "User wasn't admin.");
        //}

        //[Test]
        //public void CanChangeEditorUser()
        //{
        //    IPrincipal user = CreatePrincipal("AverageJoe");
        //    mocks.ReplayAll();

        //    security.EditorNames = new string[] { "AverageJoe" };

        //    Assert.IsTrue(security.IsEditor(user), "User wasn't editor.");
        //}

        //[Test]
        //public void CanChangeEditorRoles()
        //{
        //    IPrincipal user = CreatePrincipal("AverageJoe", "GhostWhisperer", "SiteSeeker");
        //    mocks.ReplayAll();

        //    security.EditorRoles = new string[] { "GhostWhisperer" };

        //    Assert.IsTrue(security.IsEditor(user), "User wasn't editor.");
        //}

        //private GenericPersistenceItem CreateUserAndItem()
        //{
        //    Expect.On(context).Call(context.User).Return(CreatePrincipal("JustAnyGuy")).Repeat.Any();
        //    mocks.Replay(context);

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    return root;
        //}

        //private GenericPersistenceItem SetupNormalUserAndCreateRestrictedItem()
        //{
        //    Expect.On(context).Call(context.User).Return(CreatePrincipal("JustAnyGuy")).Repeat.Any();
        //    mocks.Replay(context);

        //    GenericPersistenceItem root = CreateOneItem<Items.SecurityPage>(1, "root", null);
        //    root.AuthorizedRoles.Add(new N2.Security.AuthorizedRole(root, "Editors"));
        //    return root;
        //}
    }
}
